import os, sys
sys.path.insert(0, os.path.expanduser('~') + '/lib/python')
from mylib.gl3d.vec3 import *
from mylib.mygl import *
import array


class DrawObject():
    center = Vec3()

    cube_vert = array.array('f', [-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0,  # Front QUAD
                                  -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0,  # Back QUAD
                                  -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0,  # Up QUAD
                                  -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,  # Down QUAD
                                  -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0,  # Left QUAD
                                  1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0  # Right QUAD
                                  ])
    cube_tex = array.array('f',
                           [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
                            1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
                            1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0])
    cube_norm = array.array('f',
                            [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0,
                             0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
                             0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,
                             0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
                             0.0])
    dlist = {}

    def __init__(self, v1=None, v2=None, v3=None):
        self.set_pos(v1, v2, v3)
        self.quadratic = gluNewQuadric()
        gluQuadricNormals(self.quadratic, GLU_SMOOTH)  # Create Smooth Normals (NEW)
        gluQuadricTexture(self.quadratic, GL_TRUE)  # Create Texture Coords (NEW)
        gluQuadricDrawStyle(self.quadratic, GLU_FILL)

    def set_pos(self, v1, v2=None, v3=None):
        if type(v1) is Vec3:
            self.center = v1
        elif None not in (v1, v2, v3):
            self.center.x = v1
            self.center.y = v2
            self.center.z = v3
        else:
            self.center = Vec3()

    def glDrawLine(self, v1, v2=None, v3=None):
        glBegin(GL_LINE)
        if type(v1) is Vec3 and type(v2) is Vec3:
            glVertex3f(v1.x, v1.y, v1.z)
            glVertex3f(v2.x, v2.y, v2.z)
            self.center = v2
        elif type(v1) is Vec3:
            glVertex3f(self.center.x, self.center.y, self.center.z)
            glVertex3f(v1.x, v1.y, v1.z)
            self.center = v1
        elif None not in (v1, v2, v3):
            glVertex3f(self.center.x, self.center.y, self.center.z)
            glVertex3f(v1, v2, v3)
            self.center.x = v1
            self.center.y = v2
            self.center.z = v3
        else:
            self.center = Vec3()
        glEnd()

    def glDrawColorTri(self, x_, y_, z_, size=1.0, colors=(RGBA(r=1), RGBA(g=1), RGBA(b=1)),
                       rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'tri color %8.3f, %s, %s, %s' % (size, colors[0], colors[1], colors[2])
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_color_tri(size, colors, normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_color_tri(size, colors, normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)

    def glDrawTri(self, x_, y_, z_, size=1.0,
                  rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'tri %8.3f' % size
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_tri(size, normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_tri(size, normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)

    def glDrawQuadMT(self, x_, y_, z_, xyz=('xz', 1.0, 1.0),
                     rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):
        """
        Draw a Quad with texture coordinates
        xyz -> ('xy', x, y), ('xz', x, z), ('yz', y, z)
        """
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'quad mt %s %8.3f,%8.3f' % (xyz[0], xyz[1], xyz[2])
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_quad_mt(xyz[0], xyz[1], xyz[2], normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_quad_mt(xyz[0], xyz[1], xyz[2], normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)

    def glDrawQuad(self, x_, y_, z_, xyz=('xz', 1.0, 1.0),
                   rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):
        """
        Draw a Quad with texture coordinates
        xyz -> ('xy', x, y), ('xz', x, z), ('yz', y, z)
        """
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'quad %s %8.3f,%8.3f' % (xyz[0], xyz[1], xyz[2])
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_quad(xyz[0], xyz[1], xyz[2], normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_quad(xyz[0], xyz[1], xyz[2], normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)

    def glDrawCubeMT(self, x_, y_, z_, size=1.0, size_x=None, size_y=None, size_z=None,
                     rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):
        """Draw a cube with texture coordinates"""
        if size_x is None: size_x = size
        if size_y is None: size_y = size
        if size_z is None: size_z = size
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'cube mt %8.3f,%8.3f,%8.3f' % (size_x, size_y, size_z)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_cube_mt(size_x, size_y, size_z, normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_cube_mt(size_x, size_y, size_z, normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)

    def glDrawCube(self, x_, y_, z_, size=1.0, size_x=None, size_y=None, size_z=None,
                   rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):
        """Draw a cube with texture coordinates"""
        if size_x is None: size_x = size
        if size_y is None: size_y = size
        if size_z is None: size_z = size
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'cube %8.3f,%8.3f,%8.3f' % (size_x, size_y, size_z)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_cube(size_x, size_y, size_z, normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_cube(size_x, size_y, size_z, normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)

    def glDrawPyramid(self, x_, y_, z_, size_x=1.0, size_z=1.0, height=1.0,
                      rotate_x=None, rotate_y=None, rotate_z=None, normal=True, use_list=True, sel_name=None):  # {
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'pyramid %8.3f,%8.3f,%8.3f' % (size_x, size_z, height)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                self._draw_pyramid(size_x, size_z, height, normal)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            self._draw_pyramid(size_x, size_z, height, normal)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)
    # }

    def gluDrawSphere(self, x_, y_, z_, size=1.0, slices=32, stacks=32,
                      rotate_x=None, rotate_y=None, rotate_z=None, use_list=True, sel_name=None):  # {
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'sphere %8.3f,%d,%d' % (size, slices, stacks)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                gluSphere(self.quadratic, size, slices, stacks)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            gluSphere(self.quadratic, size, slices, stacks)

        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)
    # }

    def gluDrawCylinder(self, x_, y_, z_, base_radius=1.0, top_radius=1.0, height=1.0, slices=32, stacks=32,
                        rotate_x=None, rotate_y=None, rotate_z=None, use_list=True, sel_name=None):  # {
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'cylinder %8.3f,%8.3f,%8.3f,%d,%d' % (base_radius, top_radius, height, slices, stacks)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                gluCylinder(self.quadratic, base_radius, top_radius, height, slices, stacks)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            gluCylinder(self.quadratic, base_radius, top_radius, height, slices, stacks)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)
    # }

    def gluDrawDisk(self, x_, y_, z_, in_radius=0.0, out_radius=1.0, slices=32, loops=32,
                    rotate_x=None, rotate_y=None, rotate_z=None, use_list=True, sel_name=None):  # {
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'disk %8.3f,%8.3f,%d,%d' % (in_radius, out_radius, slices, loops)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                gluDisk(self.quadratic, in_radius, out_radius, slices, loops)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            gluDisk(self.quadratic, in_radius, out_radius, slices, loops)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)
    # }

    def gluDrawPartialDisk(self, x_, y_, z_, in_radius=0.0, out_radius=1.0, slices=32, loops=32, start_angle=0.0,
                           angle=360.0, rotate_x=None, rotate_y=None, rotate_z=None, use_list=True, sel_name=None):  # {
        glTranslatef(x_, y_, z_)
        if rotate_x is not None: glRotatef(rotate_x, 1.0, 0.0, 0.0)
        if rotate_y is not None: glRotatef(rotate_y, 0.0, 1.0, 0.0)
        if rotate_z is not None: glRotatef(rotate_z, 0.0, 0.0, 1.0)
        if sel_name is not None: glLoadName(sel_name)
        if use_list:
            key = 'partial disk %8.3f,%8.3f,%d,%d,%8.3f,%8.3f' % (in_radius, out_radius, slices, loops, start_angle, angle)
            if key in DrawObject.dlist.keys():
                glCallList(DrawObject.dlist[key])
            else:
                li = glGenLists(1)
                glNewList(li, GL_COMPILE)
                gluPartialDisk(self.quadratic, in_radius, out_radius, slices, loops, start_angle, angle)
                glEndList()
                DrawObject.dlist[key] = li
                glCallList(li)
        else:
            gluPartialDisk(self.quadratic, in_radius, out_radius, slices, loops, start_angle, angle)
        if rotate_z is not None: glRotatef(-rotate_z, 0.0, 0.0, 1.0)
        if rotate_y is not None: glRotatef(-rotate_y, 0.0, 1.0, 0.0)
        if rotate_x is not None: glRotatef(-rotate_x, 1.0, 0.0, 0.0)
        glTranslatef(-x_, -y_, -z_)
    # }

    def _draw_quad_mt(self, xyz, s1, s2, normal=True):
        glBegin(GL_QUADS)
        if xyz == 'xz':
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(-s1, 0.0, -s2)  # Top Left Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(-s1, 0.0, s2)  # Bottom Left Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(s1, 0.0, s2)  # Bottom Right Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(s1, 0.0, -s2)  # Top Right Of The Texture and Quad
        elif xyz == 'xy':
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(-s1, -s2, 0.0)  # Bottom Left Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(s1, -s2, 0.0)  # Bottom Right Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(s1, s2, 0.0)  # Top Right Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(-s1, s2, 0.0)  # Top Left Of The Texture and Quad
        else:
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, -s1, -s2)  # Bottom Right Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, s1, -s2)  # Top Right Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, s1, s2)  # Top Left Of The Texture and Quad
            glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
            glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, -s1, s2)  # Bottom Left Of The Texture and Quad
        glEnd()

    def _draw_quad(self, xyz, s1, s2, normal=True):
        glBegin(GL_QUADS)
        if xyz == 'xz':
            glTexCoord2f(0.0, 1.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(-s1, 0.0, -s2)
            glTexCoord2f(0.0, 0.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(-s1, 0.0, s2)
            glTexCoord2f(1.0, 0.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(s1, 0.0, s2)
            glTexCoord2f(1.0, 1.0)
            if normal: glNormal3f(0, 1, 0)
            glVertex3f(s1, 0.0, -s2)
        elif xyz == 'xy':
            glTexCoord2f(0.0, 0.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(-s1, -s2, 0.0)
            glTexCoord2f(1.0, 0.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(s1, -s2, 0.0)
            glTexCoord2f(1.0, 1.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(s1, s2, 0.0)
            glTexCoord2f(0.0, 1.0)
            if normal: glNormal3f(0, 0, 1)
            glVertex3f(-s1, s2, 0.0)
        else:
            glTexCoord2f(1.0, 0.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, -s1, -s2)
            glTexCoord2f(1.0, 1.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, s1, -s2)
            glTexCoord2f(0.0, 1.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, s1, s2)
            glTexCoord2f(0.0, 0.0)
            if normal: glNormal3f(1, 0, 0)
            glVertex3f(0.0, -s1, s2)
        glEnd()

    def _draw_color_tri(self, size, colors, normal):
        glBegin(GL_TRIANGLES)
        s1 = math.sin(math.radians(120)) * size  # x
        s2 = math.cos(math.radians(120)) * size  # y
        glColor4f(colors[0].r, colors[0].g, colors[0].b, colors[0].a)
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(s1, s2, 0.0)
        glColor4f(colors[1].r, colors[1].g, colors[1].b, colors[1].a)
        glTexCoord2f(0.5, 1.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(0.0, size, 0.0)
        glColor4f(colors[2].r, colors[2].g, colors[2].b, colors[2].a)
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(-s1, s2, 0.0)
        glEnd()

    def _draw_tri(self, size, normal):
        glBegin(GL_TRIANGLES)
        s1 = math.sin(math.radians(120)) * size  # x
        s2 = math.cos(math.radians(120)) * size  # y
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(s1, s2, 0.0)
        glTexCoord2f(0.5, 1.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(0.0, size, 0.0)
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(-s1, s2, 0.0)
        glEnd()

    def _draw_cube_mt(self, size_x, size_y, size_z, normal=True):
        glBegin(GL_QUADS)  # Start Drawing The Cube

        # Front Face (note that the texture's corners have to match the quad's corners)
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(-size_x, -size_y, size_z)  # Bottom Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(size_x, -size_y, size_z)  # Bottom Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(size_x, size_y, size_z)  # Top Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(-size_x, size_y, size_z)  # Top Left Of The Texture and Quad

        # Back Face
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(-size_x, -size_y, -size_z)  # Bottom Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(-size_x, size_y, -size_z)  # Top Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(size_x, size_y, -size_z)  # Top Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(size_x, -size_y, -size_z)  # Bottom Left Of The Texture and Quad

        # Top Face
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(-size_x, size_y, -size_z)  # Top Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(-size_x, size_y, size_z)  # Bottom Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(size_x, size_y, size_z)  # Bottom Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(size_x, size_y, -size_z)  # Top Right Of The Texture and Quad

        # Bottom Face
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(-size_x, -size_y, -size_z)  # Top Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(size_x, -size_y, -size_z)  # Top Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(size_x, -size_y, size_z)  # Bottom Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(-size_x, -size_y, size_z)  # Bottom Right Of The Texture and Quad

        # Right face
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, -size_y, -size_z)  # Bottom Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, size_y, -size_z)  # Top Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, size_y, size_z)  # Top Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, -size_y, size_z)  # Bottom Left Of The Texture and Quad

        # Left Face
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, -size_y, -size_z)  # Bottom Left Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, -size_y, size_z)  # Bottom Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, size_y, size_z)  # Top Right Of The Texture and Quad
        glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0)
        glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, size_y, -size_z)  # Top Left Of The Texture and Quad

        glEnd()  # Done Drawing The Cube

    def _draw_cube(self, size_x, size_y, size_z, normal=True):
        glBegin(GL_QUADS)  # Start Drawing The Cube

        # Front Face (note that the texture's corners have to match the quad's corners)
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(-size_x, -size_y, size_z)  # Bottom Left Of The Texture and Quad
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(size_x, -size_y, size_z)  # Bottom Right Of The Texture and Quad
        glTexCoord2f(1.0, 1.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(size_x, size_y, size_z)  # Top Right Of The Texture and Quad
        glTexCoord2f(0.0, 1.0)
        if normal: glNormal3f(0, 0, 1)
        glVertex3f(-size_x, size_y, size_z)  # Top Left Of The Texture and Quad

        # Back Face
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(-size_x, -size_y, -size_z)  # Bottom Right Of The Texture and Quad
        glTexCoord2f(1.0, 1.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(-size_x, size_y, -size_z)  # Top Right Of The Texture and Quad
        glTexCoord2f(0.0, 1.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(size_x, size_y, -size_z)  # Top Left Of The Texture and Quad
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(0, 0, -1)
        glVertex3f(size_x, -size_y, -size_z)  # Bottom Left Of The Texture and Quad

        # Top Face
        glTexCoord2f(0.0, 1.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(-size_x, size_y, -size_z)  # Top Left Of The Texture and Quad
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(-size_x, size_y, size_z)  # Bottom Left Of The Texture and Quad
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(size_x, size_y, size_z)  # Bottom Right Of The Texture and Quad
        glTexCoord2f(1.0, 1.0)
        if normal: glNormal3f(0, 1, 0)
        glVertex3f(size_x, size_y, -size_z)  # Top Right Of The Texture and Quad

        # Bottom Face
        glTexCoord2f(1.0, 1.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(-size_x, -size_y, -size_z)  # Top Right Of The Texture and Quad
        glTexCoord2f(0.0, 1.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(size_x, -size_y, -size_z)  # Top Left Of The Texture and Quad
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(size_x, -size_y, size_z)  # Bottom Left Of The Texture and Quad
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(0, -1, 0)
        glVertex3f(-size_x, -size_y, size_z)  # Bottom Right Of The Texture and Quad

        # Right face
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, -size_y, -size_z)  # Bottom Right Of The Texture and Quad
        glTexCoord2f(1.0, 1.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, size_y, -size_z)  # Top Right Of The Texture and Quad
        glTexCoord2f(0.0, 1.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, size_y, size_z)  # Top Left Of The Texture and Quad
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(1, 0, 0)
        glVertex3f(size_x, -size_y, size_z)  # Bottom Left Of The Texture and Quad

        # Left Face
        glTexCoord2f(0.0, 0.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, -size_y, -size_z)  # Bottom Left Of The Texture and Quad
        glTexCoord2f(1.0, 0.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, -size_y, size_z)  # Bottom Right Of The Texture and Quad
        glTexCoord2f(1.0, 1.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, size_y, size_z)  # Top Right Of The Texture and Quad
        glTexCoord2f(0.0, 1.0)
        if normal: glNormal3f(-1, 0, 0)
        glVertex3f(-size_x, size_y, -size_z)  # Top Left Of The Texture and Quad

        glEnd()  # Done Drawing The Cube


    def _draw_pyramid(self, size_x, size_z, height, normal=True):

        vCorners = [[0.0, height, 0.0],  # // Top           0
                    [-size_x, 0.0, -size_z],  # // Back left     1
                    [size_x, 0.0, -size_z],  # // Back right    2
                    [size_x, 0.0, size_z],  # // Front right   3
                    [-size_x, 0.0, size_z]]  # // Front left    4

        glBegin(GL_TRIANGLES)
        # // Bottom section - two triangles
        if normal: glNormal3f(0.0, -1.0, 0.0)
        glTexCoord2f(1.0, 1.0)
        glVertex3fv(vCorners[2])

        glTexCoord2f(0.0, 0.0)
        glVertex3fv(vCorners[4])

        glTexCoord2f(0.0, 1.0)
        glVertex3fv(vCorners[1])

        glTexCoord2f(1.0, 1.0)
        glVertex3fv(vCorners[2])

        glTexCoord2f(1.0, 0.0)
        glVertex3fv(vCorners[3])

        glTexCoord2f(0.0, 0.0)
        glVertex3fv(vCorners[4])

        # // Front Face
        # m3dFindNormal(vNormal, vCorners[0], vCorners[4], vCorners[3])
        if normal:
            vn = get_face_normal(vCorners[0], vCorners[4], vCorners[3])
            glNormal3f(vn[0], vn[1], vn[2])
        glTexCoord2f(0.5, 1.0)
        glVertex3fv(vCorners[0])
        glTexCoord2f(0.0, 0.0)
        glVertex3fv(vCorners[4])
        glTexCoord2f(1.0, 0.0)
        glVertex3fv(vCorners[3])

        # // Left Face
        # m3dFindNormal(vNormal, vCorners[0], vCorners[1], vCorners[4])
        if normal:
            vn = get_face_normal(vCorners[0], vCorners[1], vCorners[4])
            glNormal3f(vn[0], vn[1], vn[2])
        glTexCoord2f(0.5, 1.0)
        glVertex3fv(vCorners[0])
        glTexCoord2f(0.0, 0.0)
        glVertex3fv(vCorners[1])
        glTexCoord2f(1.0, 0.0)
        glVertex3fv(vCorners[4])

        # // Back Face
        # if normal: m3dFindNormal(vNormal, vCorners[0], vCorners[2], vCorners[1])
        if normal:
            vn = get_face_normal(vCorners[0], vCorners[2], vCorners[1])
            glNormal3f(vn[0], vn[1], vn[2])
        glTexCoord2f(0.5, 1.0)
        glVertex3fv(vCorners[0])

        glTexCoord2f(0.0, 0.0)
        glVertex3fv(vCorners[2])

        glTexCoord2f(1.0, 0.0)
        glVertex3fv(vCorners[1])

        # // Right Face
        # if normal: m3dFindNormal(vNormal, vCorners[0], vCorners[3], vCorners[2])
        if normal:
            vn = get_face_normal(vCorners[0], vCorners[3], vCorners[2])
            glNormal3f(vn[0], vn[1], vn[2])
        glTexCoord2f(0.5, 1.0)
        glVertex3fv(vCorners[0])
        glTexCoord2f(0.0, 0.0)
        glVertex3fv(vCorners[3])
        glTexCoord2f(1.0, 0.0)
        glVertex3fv(vCorners[2])
        glEnd()
